/*
 * @lc app=leetcode.cn id=51 lang=cpp
 *
 * [51] N 皇后
 *
 * https://leetcode-cn.com/problems/n-queens/description/
 *
 * algorithms
 * Hard (74.01%)
 * Likes:    1314
 * Dislikes: 0
 * Total Accepted:    211K
 * Total Submissions: 285.1K
 * Testcase Example:  '4'
 *
 * n 皇后问题 研究的是如何将 n 个皇后放置在 n×n 的棋盘上，并且使皇后彼此之间不能相互攻击。
 * 
 * 给你一个整数 n ，返回所有不同的 n 皇后问题 的解决方案。
 * 
 * 
 * 
 * 每一种解法包含一个不同的 n 皇后问题 的棋子放置方案，该方案中 'Q' 和 '.' 分别代表了皇后和空位。
 * 
 * 
 * 
 * 示例 1：
 * 
 * 
 * 输入：n = 4
 * 输出：[[".Q..","...Q","Q...","..Q."],["..Q.","Q...","...Q",".Q.."]]
 * 解释：如上图所示，4 皇后问题存在两个不同的解法。
 * 
 * 
 * 示例 2：
 * 
 * 
 * 输入：n = 1
 * 输出：[["Q"]]
 * 
 * 
 * 
 * 
 * 提示：
 * 
 * 
 * 1 <= n <= 9
 * 
 * 
 * 
 * 
 */

// @lc code=start
class Solution {
// private:
//     vector<vector<string>> res;
//     void backtracking(int n, int row, vector<string>& chessboard) {
//         if(row == n) {
//             res.push_back(chessboard);
//             return;
//         }

//         for(int col = 0; col < n; col++) {
//             if(isValid(row, col, chessboard, n)) {
//                 chessboard[row][col] = 'Q';
//                 backtracking(n, row+1, chessboard);
//                 chessboard[row][col] = '.';
//             }
//         }
//     }
//     bool isValid(int row, int col, const vector<string> chessboard, int n) {
//         //判断某一列的所有行是否符合要求
//         for(int i = 0; i < row; i++) {
//             if(chessboard[i][col] == 'Q') return false;
//         }

//         //检查45度斜线
//         for(int i = row - 1, j = col - 1; i >= 0 && j >= 0; i--, j--) {
//             if(chessboard[i][j] == 'Q') return false;
//         }

//         //检查135度斜线
//         for(int i = row -1, j = col + 1; i >= 0 && j < n; i--, j++) {
//             if(chessboard[i][j] == 'Q') return false;
//         }
//         return true;
//     }
// public:
//     vector<vector<string>> solveNQueens(int n) {
//         res.clear();
//         vector<string> chessboard(n, string(n, '.'));
//         backtracking(n, 0, chessboard);
//         return res;
//     }

private:
    vector<vector<string>> res;
    bool isValid(int row, int col, int n, vector<string> chessboard) {
        // for(int i = 0; i <= n; i++) {
        //     if(chessboard[row][i] == 'Q') return false;
        // }
        for(int i = 0; i < row; i++) {
            if(chessboard[i][col] == 'Q') return false;
        }

        for(int i = row - 1, j = col - 1; i >= 0 && j >= 0; i--, j--) {
            if(chessboard[i][j] == 'Q') return false;
        }

        for(int i = row - 1, j = col + 1; i >= 0 &&  j < n; i--, j++) {
            if(chessboard[i][j] == 'Q') return false;
        }
        
        return true;
    }

    void backtracking(vector<string>& chessboard, int row, int n) {
        if(row == n) {
            res.push_back(chessboard);
        }

        for(int col = 0; col < n; col++) {
            if(isValid(row, col, n, chessboard)) {
                chessboard[row][col] = 'Q';
                backtracking(chessboard, row + 1, n);
                chessboard[row][col] = '.';
            }
        }
    }
public:
    vector<vector<string>> solveNQueens(int n) {
        res.clear();
        vector<string> chessboard(n, string(n, '.'));

        backtracking(chessboard, 0, n);

        return res;
    }
};
// @lc code=end

